package base.thread_JUC.demo05;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 由数组结构组成的阻塞队列 ArrayBlockingQueue 演示，队列特点：FIFO
 */
public class BlockingQueueTest {
    public static void main(String[] args) {
        // 会抛出异常的接口演示
//        testCase1();

        // 返回特殊值的接口演示
//        testCase2();

        // 会阻塞的接口演示，不推荐使用，使用要小心
//       testCase3_1();

        // 指定等待时间的阻塞接口演示，推荐使用
        testCase4();


    }

    /**
     * 当遇到队列阻塞时，等候指定时间，还阻塞就结束往队列添加元素/取出元素
     */
    public static void testCase4(){
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);

        try {
            System.out.println(blockingQueue.offer("a", 2, TimeUnit.SECONDS));
            System.out.println(blockingQueue.offer("b", 2, TimeUnit.SECONDS));
            System.out.println(blockingQueue.offer("c", 2, TimeUnit.SECONDS));
            System.out.println(blockingQueue.offer("x", 2, TimeUnit.SECONDS));// 阻塞2s

            System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));
            System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));
            System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));
            System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));// 阻塞2s

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    public static void testCase3_1() {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        testCase3(blockingQueue);

        // 已经被 testCase3(blockingQueue) 阻塞，下面程序不可达执行.
        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(5);
                System.out.println(Thread.currentThread().getName()+"\t 再往队列中添加一个元素: d");
                blockingQueue.put("d");
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }).start();
    }

    /**
     * 会阻塞的队列接口有 put、take
     */
    public static void testCase3(BlockingQueue<String> blockingQueue){
//        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);

        try {
            blockingQueue.put("a");
            blockingQueue.put("b");
            blockingQueue.put("c");
//            blockingQueue.put("x");// 队列阻塞挂起

            System.out.println(blockingQueue.take());
            System.out.println(blockingQueue.take());
            System.out.println(blockingQueue.take());
            System.out.println(blockingQueue.take());// 队列阻塞挂起

            // 程序不可达执行
//            TimeUnit.SECONDS.sleep(5);
//            new Thread(()->{
//                try {
//                    System.out.println(Thread.currentThread().getName()+"\t 再往队列中添加一个元素: d");
//                    blockingQueue.put("d");
//                }catch (InterruptedException e){
//                    e.printStackTrace();
//                }
//
//            }).start();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 返回特殊值的接口有 offer、peek、poll
     */
    public static void testCase2(){
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);

        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        System.out.println(blockingQueue.offer("x"));// 超出队列容量，返回false

        System.out.println(blockingQueue.peek());// 检查队首元素并返回，没有就返回null，而不是抛出异常

        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());//移除队首元素，没有返回null

    }

    /**
     * 抛出异常的接口有 add、element、remove
     */
    public static void testCase1(){
        //        List<String> list = new ArrayList<>();//默认初始容量 10
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue(3);

        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));

        System.out.println(blockingQueue.element());

        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());

        System.out.println(blockingQueue.element()); // NoSuchElementException
    }
}
